package com.xu.t1.middleware.threadallocation;

import com.xu.t1.mapper.UploadLogMapper;
import com.xu.t1.middleware.Thread.ThreadCounterService;
import com.xu.t1.middleware.online.OnlineUserManager;
import com.xu.t1.model.ThreadAllocationContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


@Component
public class ThreadHandler3 implements ThreadAllocationHandler {

    @Value("${app.server-id}")
    private String serverId;

    private ThreadAllocationHandler nextHandler;

    @Autowired
    private UploadLogMapper uploadLogMapper;

    @Autowired
    private OnlineUserManager onlineUserManager;

    @Override
    public boolean handle(ThreadAllocationContext context) {

        // 平均单位人数线程使用量
        context.setAvgThreadCont((int) Math.floor(uploadLogMapper.avgThreadCont(serverId)));

        // 平均任务处理时间（锚定的单位时间）
        context.setAvgDuration((int) Math.floor(uploadLogMapper.avgDurationMs(serverId) / 1000));

        // 当前节点指定时间历史人数
        int historyOnline = onlineUserManager.getOnlineHistory(serverId, context.getAvgDuration() * context.getAverageSampleSize());

        // 当前节点当前人数
        int serverOnlineUsers = context.getServerOnlineUsers();

        // 单位时间平均人数增量 负数置为0
        int averageOnlineGrowthRate = Math.max(0, (serverOnlineUsers - historyOnline) / context.getAverageSampleSize());

        // 应该保留的线程数
        int reservedThreads = averageOnlineGrowthRate * context.getAvgThreadCont();
        int maxReserve = (int) (context.getAllocatableThreads() * context.getMaxThreadReserveRatio());

        // 限定最大保留数
        int finalReservedThreads = Math.min(reservedThreads, maxReserve);
        context.setAllocatableThreads(context.getAllocatableThreads() - finalReservedThreads);

        return nextHandler.handle(context);

    }

    @Override
    public ThreadAllocationHandler setNext(ThreadAllocationHandler nextHandler) {
        this.nextHandler = nextHandler;
        return nextHandler;
    }
}